RE, WA, TLE対策
ABCでRE,WA,TLEになって対応するとき,知っておくと良いことをまとめておこう.(随時追記求む!)主にPython向けです.
◎RE
サンプルだとACなのに,投稿したらRE!というときのTIPS.
配列外参照
for文で配列外まで参照する.【対策】配列アクセスする前に,ifで作成した配列範囲内か確認する.rangeの終了条件設定で配列外にアクセスしないようにする手もあるが,range(1, 10)だと10は含まないこと,0-indexと1-indexで混乱することを考えると,ifで対応する方が確実か.
必要なだけ配列を作っていない.例:高さH,幅Wを読み込んで,大きさHの配列が必要なのに,間違って大きさWで作っていた.【対策】作成した配列サイズを確認しよう.
C/C++だと配列外参照してもエラーが出ない..at()するか,コンパイルオプション付けて検出する.
PyPyで使えないモジュール/関数の利用
PyPyで提出したときに,PyPyで未対応のモジュールや,未対応のPythonバージョンで追加された関数を利用する.【対策】Pythonで提出する.
コードテストで実行すれば標準エラー出力が見れるので,どのモジュールでエラーが出ているか確認できる
環境構築できるなら,ローカルの環境をジャッジに合わせるのも良いかも.
maxやminの引数に指定したリストが空
解の候補をリストkouhoに入れて,その最大値を獲得するためにmax(kouho)を使うとき,kouhoが空の場合,REになる.【対策】リストが空になる可能性があるなら,if len(kouho) > 0のように確認してから実行する.
if文の中で変数を初期化
if文の中で初期化した変数をそれ以降で使用している時に、その条件を満たさないケースがあった場合、初期化されていない変数を使用することになってしまい、REになる.
◎WA
絶対やり方あっているのに,なぜWA!!というときのTIPS.
計算誤差
実数計算,特に割り算(/)による計算誤差.sqrtによる計算誤差も,多数合計して累積すると問題になることも.【対策】(1)Decimalモジュールを使う.(2)整数割り算(//)で済ませられるよう工夫する.特に,A/Bの切り上げ(A+B-1)//Bは有用.(3)数学的に式変形して,割り算を使わないで済むようにする.
コーナーケース
値設定の下限や上限のときに生じる特別な場合に対応できていない.【対策】問題の「制約」を確認して,特別な処理が必要なコーナーケースがないか確認する.
ローカルで,ランダム生成したテストケースを試すスクリプトを書いてコーナーケースを探せると嬉しい.
(ペナルティを気にしないのであれば)適宜assertしてREになるか確認する手もある.
0-index, 1-index
リストは0開始の0-indexなのに対して,入力データの多くは1開始の1-indexであることによって起こるミス.【対策】0-indexにするなら,データ読み込み時に-1しておく.1-indexにするなら,データ領域を余分に取る.自分にとって分かりやすい方を使う.どちらのindexなのかコメントに入れるのも効果的.
デバッグ出力削除ミス
デバッグ用に追加していたprintの消し忘れ.最後に試した入力例では処理されなかった部分にprintが残っていた!というケースもまれにあるので注意.【対策】注意してコメントアウトする(しかないの?)
Yuto.icon コメントアウト以外にもいくつか方法はあります.私が使っている手法を紹介します.
1. __debug__フラグを使う
ローカルで実行する時にpython -O hoge.py(ゼロじゃなくて大文字オー)とすれば,__debug__ == Falseとなる.ファイル先頭でLOCAL = not (__debug__)として,デバッグ出力時にif LOCAL: print(...)すればok
2. ラッパーを実装する
def eprint(*args): print(*args, file=sys.stderr)として,デバッグ出力時はeprint(...)すればok
出力形式ミス
YesかNoかを出力するのにYESとNO(全て大文字)を出力するように作ってしまう.本質的には合っているので,間違いに気付きにくい. 【対策】「出力」をよく読んで,求められている形式の出力を行う
環境構築が得意なら,ローカルでジャッジするスクリプト(ojtとか)を導入すると良いですね.私は環境構築した時にojtなどの存在を知らなかったので,スクリプトを自作しました.
◎TLE
サンプルだとACなのに,投稿したらTLE!というときのTIPS.全体的にTLEのときと,少しのケースでTLEのときで対応が異なるね.
アルゴリズムの計算量が大きい
入力のサイズを確認して,最悪の場合に計算量が$ O(10^6)を超える方法.【対策】方針を見直す.勉強して知識を増やす.
PyPyの苦手なことをしている
概してPythonより速いPyPyにも,Pythonより実行速度が遅くなる処理もある.例:文字列の連結,再帰処理,Decimalモジュールの利用.【対策】これらの処理を使わない,またはPythonで実行する.
無限ループ
バグによる無限ループ.サンプルだと生じなかったが,複雑なデータだと生起する.BFS/DFSで,適切にvisitedを設定できていない場合が代表例.【対策】探索処理があるときは,無限ループになっていないか確認する.
微妙に時間のかかる処理を行っている
計算量では問題なくても,PythonやPyPyの仕様上,想像より時間がかかる処理もある.以下例示.
集合や辞書Aに対するx in A.$ O(1)だけど,Aがやや複雑だと時間がかかるみたい.【対策】True/Falseを保持するリストで代用する.
float('inf')を多用する.大きな値として∞を表すfloat('inf')だけど,何度も利用すると時間がかかるみたい.【対策】(1) 1<<60を使う (2) 10**18を使う.(3) INF = float('inf')として変数に代入しておく.参考サイト
多次元リスト内の離れた位置を続けてアクセスする.例えば,A[i][j]を行i列jの位置とすると,Aは2次元リストA=[[1行目の内容], [2行目の内容], ..., [n行目の内容]]となっている.そのため,同じ行内で(横方向に)順に位置を確認するようなfor文と比べ,同じ列内で(縦方向に)順に位置を確認するようなfor文は処理が遅くなるようです.頻出の2次元盤面を使う問題では仕方ありませんが,多次元DPの場合,各次元の添え字の順番を変えるだけで処理時間が異なります.【対策】多次元DPでは内側のforで変化させる要素をDPテーブルの後ろの方にする.
#ABC #初心者向け #Python